import { Injectable, NotFoundException, ForbiddenException, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Notification, NotificationType, SourceType } from '../../entities/notification.entity';
import { CreateNotificationDto } from './dto/create-notification.dto';
import { TaskService } from '../task/task.service';
import { TaskCommentService } from '../task/task-comment.service';
import { TaskCommentReplyService } from '../task/task-comment-reply.service';

@Injectable()
export class NotificationService {
  private readonly logger = new Logger(NotificationService.name);

  constructor(
    @InjectRepository(Notification)
    private notificationRepository: Repository<Notification>,
    private taskService: TaskService,
    private taskCommentService: TaskCommentService,
    private taskCommentReplyService: TaskCommentReplyService,
  ) {}

  /**
   * 创建通知
   */
  async createNotification(createNotificationDto: CreateNotificationDto): Promise<Notification> {
    const notification = this.notificationRepository.create(createNotificationDto);
    this.logger.log(`创建通知: ${JSON.stringify(createNotificationDto)}`);
    return this.notificationRepository.save(notification);
  }

  /**
   * 获取用户的所有通知
   */
  async getUserNotifications(
    userId: string, 
    options?: { page?: number; limit?: number; isRead?: boolean }
  ): Promise<{ notifications: Notification[]; total: number }> {
    const { page = 1, limit = 10, isRead } = options || {};
    
    const queryBuilder = this.notificationRepository.createQueryBuilder('notification')
      .leftJoinAndSelect('notification.user', 'user')
      .where('notification.userId = :userId', { userId });
    
    if (isRead !== undefined) {
      queryBuilder.andWhere('notification.isRead = :isRead', { isRead });
    }
    
    const [notifications, total] = await queryBuilder
      .orderBy('notification.createdAt', 'DESC')
      .skip((page - 1) * limit)
      .take(limit)
      .getManyAndCount();
    
    return { notifications, total };
  }

  /**
   * 获取单个通知
   */
  async getNotificationById(id: string, userId: string): Promise<Notification> {
    const notification = await this.notificationRepository.findOne({
      where: { id },
      relations: ['user']
    });
    
    if (!notification) {
      throw new NotFoundException(`通知ID ${id} 不存在`);
    }
    
    if (notification.userId !== userId) {
      throw new ForbiddenException('您没有权限查看此通知');
    }
    
    return notification;
  }

  /**
   * 将通知标记为已读
   */
  async markAsRead(id: string, userId: string): Promise<Notification> {
    const notification = await this.getNotificationById(id, userId);
    
    notification.isRead = true;
    return this.notificationRepository.save(notification);
  }

  /**
   * 将用户所有通知标记为已读
   */
  async markAllAsRead(userId: string): Promise<void> {
    await this.notificationRepository.update(
      { userId, isRead: false },
      { isRead: true }
    );
    this.logger.log(`用户 ${userId} 的所有通知标记为已读`);
  }

  /**
   * 删除通知
   */
  async deleteNotification(id: string, userId: string): Promise<void> {
    const notification = await this.getNotificationById(id, userId);
    await this.notificationRepository.remove(notification);
    this.logger.log(`删除通知 ${id} 成功`);
  }

  /**
   * 发送任务分配通知
   */
  async sendTaskAssignmentNotification(taskId: string, assigneeId: string): Promise<void> {
    try {
      // 获取任务详情
      const task = await this.taskService.getTaskById(taskId);
      if (!task) {
        this.logger.error(`任务不存在: ${taskId}`);
        return;
      }

      const notification = {
        title: '任务已分配给您',
        content: `您有一个新的任务需要处理：${task.title}`,
        type: NotificationType.TASK_ASSIGNMENT,
        userId: assigneeId,
        sourceId: taskId,
        sourceType: SourceType.TASK,
      } as CreateNotificationDto;

      await this.createNotification(notification);
      this.logger.log(`发送任务分配通知: 任务 ${taskId} 分配给 ${assigneeId}`);
    } catch (error) {
      this.logger.error(`发送任务分配通知失败: ${error.message}`);
    }
  }

  /**
   * 发送任务评论通知
   */
  async sendTaskCommentNotification(commentId: string, taskId: string): Promise<void> {
    try {
      const task = await this.taskService.getTaskById(taskId);
      const comment = await this.taskCommentService.getCommentById(commentId);
      
      if (!task || !comment) {
        this.logger.error(`任务或评论不存在: taskId=${taskId}, commentId=${commentId}`);
        return;
      }
      
      // 通知任务所有者和被分配人（如果不是评论者自己）
      if (task.createdById !== comment.userId) {
        await this.createNotification({
          title: '您的任务有新评论',
          content: `您的任务"${task.title}"收到了新评论: ${comment.content.substring(0, 30)}${comment.content.length > 30 ? '...' : ''}`,
          type: NotificationType.TASK_COMMENT,
          userId: task.createdById,
          sourceId: commentId,
          sourceType: SourceType.COMMENT,
        } as CreateNotificationDto);
        this.logger.log(`发送任务评论通知: 评论 ${commentId} 给任务所有者 ${task.createdById}`);
      }
      
      if (task.assigneeId && task.assigneeId !== comment.userId && task.assigneeId !== task.createdById) {
        await this.createNotification({
          title: '您负责的任务有新评论',
          content: `您负责的任务"${task.title}"收到了新评论: ${comment.content.substring(0, 30)}${comment.content.length > 30 ? '...' : ''}`,
          type: NotificationType.TASK_COMMENT,
          userId: task.assigneeId,
          sourceId: commentId,
          sourceType: SourceType.COMMENT,
        } as CreateNotificationDto);
        this.logger.log(`发送任务评论通知: 评论 ${commentId} 给任务负责人 ${task.assigneeId}`);
      }
    } catch (error) {
      this.logger.error(`发送任务评论通知失败: ${error.message}`);
    }
  }

  /**
   * 发送评论回复通知
   */
  async sendCommentReplyNotification(replyId: string, commentId: string): Promise<void> {
    const reply = await this.taskCommentReplyService.getReplyById(replyId);
    const comment = await this.taskCommentService.getCommentById(commentId);
    
    // 如果回复者不是评论者，则通知评论者
    if (reply.userId !== comment.userId) {
      await this.createNotification({
        title: '您的评论收到了新回复',
        content: `您的评论收到了新回复：${reply.content.substring(0, 30)}${reply.content.length > 30 ? '...' : ''}`,
        type: NotificationType.COMMENT_REPLY,
        userId: comment.userId,
        sourceId: replyId,
        sourceType: SourceType.REPLY,
      } as CreateNotificationDto);
      this.logger.log(`发送评论回复通知: 回复 ${replyId} 给评论者 ${comment.userId}`);
    }
  }

  /**
   * 发送任务截止日期提醒
   */
  async sendTaskDueDateNotification(taskId: string): Promise<void> {
    try {
      const task = await this.taskService.getTaskById(taskId);
      if (!task || !task.assigneeId) {
        this.logger.error(`任务不存在或未分配: ${taskId}`);
        return;
      }

      // 通知任务负责人
      await this.createNotification({
        title: '任务即将到期',
        content: `您负责的任务"${task.title}"即将到期，请尽快完成`,
        type: NotificationType.TASK_DUE_DATE,
        userId: task.assigneeId,
        sourceId: taskId,
        sourceType: SourceType.TASK,
      } as CreateNotificationDto);
      this.logger.log(`发送任务截止日期提醒: 任务 ${taskId} 给负责人 ${task.assigneeId}`);
      
      // 通知任务创建者（如果不是同一人）
      if (task.createdById !== task.assigneeId) {
        await this.createNotification({
          title: '您创建的任务即将到期',
          content: `您创建的任务"${task.title}"即将到期`,
          type: NotificationType.TASK_DUE_DATE,
          userId: task.createdById,
          sourceId: taskId,
          sourceType: SourceType.TASK,
        } as CreateNotificationDto);
        this.logger.log(`发送任务截止日期提醒: 任务 ${taskId} 给创建者 ${task.createdById}`);
      }
    } catch (error) {
      this.logger.error(`发送任务截止日期通知失败: ${error.message}`);
    }
  }
} 